function LeagueBoss() { 

    this.bosses = {
        /*
        league_name: {
            'level': 0,
            'blood':0,
            'kill':0,
            'kill_reward':0,
            'top': [],
            'day':0, 
        } 
        */
    };

    this.hurts = {};
    this.updates = {}; 
    this.sortTime = {};
} 
 
LeagueBoss.create = function() { 
    gDBWorld.insert({_id: 'league_boss', league_boss: {}}, function(err, result){}); 
}; 
 
LeagueBoss.prototype = { 
     
    init: function(callback) { 
        gDBWorld.findOne({_id : 'league_boss'}, {}, function(err, doc){ 
            if( doc ) {
                this.bosses = doc.league_boss;
                this._init();
                callback && callback(true);
            }else{
                callback && callback(false);
            }    
        }.bind(this));
    },

    _init: function() {
        for( var leagueName in this.bosses ) {
            var hurts = {};
            this.hurts[leagueName] = hurts;
            var boss = this.bosses[leagueName];
            boss.top.forEach(function(user){
                hurts[user.uid] = user.hurt;
            });
        }
    },

    updateBoss: function(leagueName) {
        // 更新军团boss
        if( !this.isUnderBoss() ){
            return false; 
        }

        var leagueLevel = gLeague.leagues[leagueName].level;
        var confLeagueBoss = gConfLeagueBoss[leagueLevel];
        var confMonster = gConfMonster[confLeagueBoss.Boss];

        var boss = this.bosses[leagueName];
        if( boss && boss.day == common.getDate() ){
            return false;
        }

        // 重置boss
        boss = {
            'level': leagueLevel,
            'blood': confMonster.Health,
            'kill':  0,
            'kill_reward': 0,
            'top': [],
            'day': common.getDate()
        };

        this.bosses[leagueName] = boss;
        this.hurts[leagueName] = {};

        this.addUpdate(leagueName, boss);
        
        return true;
    },

    getBoss: function(leagueName) {
        return this.bosses[leagueName];
    },

    addUpdate: function(key, value) {
        this.updates['league_boss.'+key] = value;
    },

    save: function(callback) {
        if( Object.keys(this.updates).length == 0 ) {
            return;
        }    
             
        gDBWorld.update({_id : 'league_boss'}, {$set: this.updates}, function(err, result){ 
            if( err ) {
                callback && callback(false);
            }else {
                callback && callback(true);
            }    
        });  

        this.updates = {};   
    },

    addHurt: function(leagueName, uid, hurt) {
        var hurts = this.hurts[leagueName];
        if( !hurts ) {
            hurts = {};
            this.hurts[leagueName] = hurts;
        }
        
        var newUser = false;
        if( uid in hurts ) {
            hurts[uid] += hurt;
        }else{
            newUser = true;
            hurts[uid] = hurt;
        }

        var nowTime = common.getTime();
        var sortTime = this.sortTime[leagueName] || 0;
        var boss = this.bosses[leagueName];

        var confLeagueBoss = gConfLeagueBoss[boss.level];
        var confMonster = gConfMonster[confLeagueBoss.Boss];
        var bossBloodLeft =  boss.blood / confMonster.Health; 

        if( (nowTime - sortTime) >= 60 || boss.kill || newUser || bossBloodLeft < 0.1 ) { 
            var top = [];
            for( var uid in hurts ) {
                var userInfo = gUserInfo.getUser(uid);
                top.push({'uid':uid, 'hurt':hurts[uid]});
            }

            top.sort(function(obj1, obj2){
                return obj2.hurt - obj1.hurt;
            });

            boss.top = top;

            this.sortTime[leagueName] = nowTime; 
            this.addUpdate(leagueName+'.top', boss.top)
        }
    },

    isUnderBoss : function() {
        var today = new Date();
        var todayStartTime = +(new Date(today.getFullYear(), today.getMonth(), today.getDate()))/1000;

        bossStartTime = todayStartTime + gConfGlobal.LeagueBossStartHour*3600 - 10;
        bossEndTime =  todayStartTime + gConfGlobal.LeagueBossEndHour*3600 + 10;

        var now = common.getTime(); 
        if( (now < bossStartTime)  || (now > bossEndTime) ) {
            return false; 
        }

        return true;
    },
}   

exports.get = function(req, resp, onHandled) {
    do{
        var uid = req.uid;
        var leagueName = req.args.league_name;

        var leagueLevel = gLeague.leagues[leagueName].level;
        var confLeagueBoss = gConfLeagueBoss[leagueLevel];
        if( !confLeagueBoss ) {
            resp.code=1; resp.desc='invalid league level'; break;
        }

        gLeagueBoss.updateBoss(leagueName);

        var boss = gLeagueBoss.getBoss(leagueName);
        if( !boss ) {
            break;
        }

        var kill_reward = 0;
        var kill_name = '';
        var join_reward = 0;
        var rank5 = [];

        if( boss.kill ) {
            var top = boss.top.slice(0,5);
            top.forEach(function(obj) {
                var userInfo = gUserInfo.getUser(obj.uid);
                rank5.push({'name': userInfo.name, 'headpic': userInfo.headpic } ); 
            });

            // 参与奖
            var top = boss.top;
            for( var i=1,len=top.length; i<=len; i++ ) {
                if( uid == top[i-1].uid ) {
                    break;
                }
            }

            var myRankType = 0;
            if( i == 1 ) {
                myRankType = 1;
            }else if( i<6 ) {
                myRankType = 2;
            }else if( i<16 ) {
                myRankType = 3;
            }else{
                myRankType = 4;
            }

            if( i == len+1 ) {
                join_reward = 0;
            }else {
                if( req.args.join == boss.day && req.args.got_reward != boss.day ) {
                    join_reward = myRankType;
                } else if(req.args.join == boss.day && req.args.got_reward == boss.day ) {
                    join_reward = -myRankType;
                } else {
                    join_reward = 0; 
                }
            }

            // 击杀奖
            if( boss.kill ) {
                var userInfo = gUserInfo.getUser(boss.kill);
                kill_name = userInfo.name; 
            }

            if( req.uid != boss.kill ) {
                kill_reward = 0;
            }else {
                kill_reward = boss.kill_reward;
            }
        }

        resp.data.bossid = boss.day;
        resp.data.kill_reward = kill_reward;
        resp.data.boss_level = boss.level;
        resp.data.kill_name = kill_name;
        resp.data.join_reward = join_reward;
        resp.data.rank5 = rank5;

        gLeagueBoss.save();

    }while(false);

    onHandled();
}

exports.rank = function(req, resp, onHandled) {
    do {  
        var boss = gLeagueBoss.getBoss(req.args.league_name);
        if( !boss ) {
            resp.code=1; resp.desc='no boss'; break;
        }

        var rankUserInfo = [];
        boss.top.forEach(function(obj) {
            var userInfo = gUserInfo.getUser(obj.uid);
            rankUserInfo.push({'name': userInfo.name});
        });

        resp.data.rank = boss.top;        
        resp.data.user_info = rankUserInfo;

    }while(false) ;
    
    onHandled();
} 

exports.get_kill_reward = function(req, resp, onHandled) {
    do {
        var leagueName = req.args.league_name;
        var boss = gLeagueBoss.getBoss(leagueName);
        if( !boss ) {
            resp.code=1; resp.desc='no boss'; break;
        }
       
        if( boss.kill != req.uid || boss.kill_reward != 1 ) {
            resp.code = 1; resp.desc = 'no reward'; break;
        }

        boss.kill_reward = -1;
        gLeagueBoss.addUpdate(leagueName+'.kill_reward', -1);

        gLeagueBoss.save();

    }while(false); 

    onHandled();
}

exports.get_reward = function(req, resp, onHandled) {
    do {
        var leagueName = req.args.league_name;
        var boss = gLeagueBoss.getBoss(leagueName);

        if( !boss || !boss.kill) {
            resp.code=1; resp.desc='no boss or kill'; break;
        }

        if( req.args.got_reward == boss.day ) {
            resp.code= 1; resp.desc='got';break;
        }
        
        var rank = 0;
        var top = boss.top;
        for( var i=1,len=top.length; i<=len; i++ ) {
            if( req.uid == top[i-1].uid ) {
                rank = i;
                break;
            }
        }

        if( rank <= 0 ) {
            resp.code=1; resp.desc='not join'; break;
        }

        var leagueBossRewardConf = gConfLeagueBossReward[rank];
        if( !leagueBossRewardConf ) {
            leagueBossRewardConf = gConfLeagueBossReward.win;
        }

        var awards = [];
        if( leagueBossRewardConf ) {
            awards = [leagueBossRewardConf.Award1, leagueBossRewardConf.Award2];

            var gold = leagueBossRewardConf.Gold + leagueBossRewardConf.LevelGold * (boss.level -1);
            awards.push(['user','gold', gold]);

            var soul = leagueBossRewardConf.Soul + leagueBossRewardConf.LevelSoul * (boss.level-1);
            awards.push(['user','soul', soul]);
        }

        resp.data.bossid = boss.day;
        resp.data.awards = awards;

    }while(false);
    
    onHandled();
}

exports.fight = function(req, resp, onHandled) {
    do {
        var uid = req.uid;
        var leagueName = req.args.league_name;
        var boss = gLeagueBoss.getBoss(leagueName);
        if( !boss ) {
            resp.code=1; resp.desc='no boss'; break;
        }

        if( boss.day != req.args.join ) {
            resp.code = 1; resp.desc = 'not ever update user data'; break;
        }

        if( boss.kill ) {
            resp.data.killed = 1; break;
        }
        
        var oldBossBlood = boss.blood;
        var leagueBossConf = gConfLeagueBoss[boss.level];
        if( !leagueBossConf ) {
            resp.code = 1; resp.desc = 'invalid boss level'; break;
        }

        fightLeagueBoss(uid, leagueBossConf, oldBossBlood, function(battleReport) {
            if( !battleReport ) {
                resp.code = 1; resp.desc = 'fight boss error';
                onHandled();
                return;
            }

            var bloodLeft = battleReport.def_remain_health;
            var hurt = oldBossBlood - bloodLeft;
            boss.blood = bloodLeft;
            gLeagueBoss.addUpdate(leagueName+'.blood', bloodLeft);

            gLeagueBoss.addHurt(leagueName, uid, hurt);

            var success = battleReport.success;
            if( success ) {
                boss.kill = uid;
                gLeagueBoss.addUpdate(leagueName+'.kill', uid ); 

                boss.kill_reward = 1;
                gLeagueBoss.addUpdate(leagueName+'.kill_reward', 1 );

            }   

            resp.data.battle = battleReport;
            resp.data.time = common.getTime();

            gLeagueBoss.save();  
            onHandled();
        });

        return;
    }while(false);

    onHandled();
}

exports.boss_blood = function(req, resp, onHandled) {
    do{
        var boss = gLeagueBoss.getBoss(req.args.league_name);
        if( !boss ) {
            resp.code=1; resp.desc='no boss'; break; 
        }

        if( req.args.join != boss.day ) {
            resp.code = 1; resp.desc = 'not ever update user data'; break;
        }

        resp.data.blood = boss.blood; 
        resp.data.killed = boss.blood>0 ? 0 : 1; 

    }while(false);

    onHandled();
}

exports.LeagueBoss = LeagueBoss;
